package cc.rengu.igas.mcps.core.service.trans.scanpay;

import cc.rengu.igas.mcps.common.constant.McpsParamConstant;
import cc.rengu.igas.mcps.common.constant.McpsTreeNodeConstant;
import cc.rengu.igas.mcps.common.enums.RespCodeEnum;
import cc.rengu.igas.mcps.core.service.base.C2BAuthService;
import cc.rengu.igas.mcps.facade.bean.OrderInfoBean;
import cc.rengu.igas.mcps.facade.request.PosScanQrCodePreAuthCancelRequest;
import cc.rengu.igas.mcps.facade.response.PosScanQrCodePreAuthCancelResponse;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;


/**
 * 条码预授权撤销
 *
 * @version 1.0.0
 * @date 2021/8/12 16:16
 */
public class PosScanQrCodePreAuthCancelService extends C2BAuthService implements TransCustomImpl {

    @Override
    protected Object bizBeforeCust() throws Exception {
        PosScanQrCodePreAuthCancelRequest posScanQrCodePreAuthCancelRequest = new PosScanQrCodePreAuthCancelRequest();
        ConvertUtil.convertOutput(posScanQrCodePreAuthCancelRequest);
        return posScanQrCodePreAuthCancelRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        PosScanQrCodePreAuthCancelRequest posScanQrCodePreAuthCancelRequest = (PosScanQrCodePreAuthCancelRequest) request;
        String instId = posScanQrCodePreAuthCancelRequest.getHeader().getInstId();
        String mchntNo = posScanQrCodePreAuthCancelRequest.getMchntNo();

        /* 获取商户信息 */
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(instId,mchntNo);
        if (null == mchntInfo) {
            rglog.error("查询商户基本信息失败<{}>", mchntNo);
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }

        /* 登记用户订单和商户订单 */
        OrderInfo orderInfo = new OrderInfo();
        OrderService orderService = new OrderServiceImpl();
        UserOrderInfo userOrderInfo = generateUserOrderInfo(posScanQrCodePreAuthCancelRequest);
        MchntOrderInfo mchntOrderInfo = generateMchntOrderInfo(posScanQrCodePreAuthCancelRequest, userOrderInfo);
        List<MchntOrderInfo> mchntOrderInfoList = new ArrayList<>();
        mchntOrderInfoList.add(mchntOrderInfo);
        orderInfo.setUserOrderInfo(userOrderInfo);
        orderInfo.setMchntOrderInfoList(mchntOrderInfoList);
        boolean iReturnCode = orderService.registerOrderInfo(userOrderInfo, mchntOrderInfoList, null);
        if (!iReturnCode) {
            rglog.error("登记支付订单信息失败!");
            throw new BizException(RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.INSERT_ORDER_INFO_ERROR.getRespDesc());
        }

        /* 调用通道接口 */
        if (null == txnInfo.getChannelCallCfgList() || txnInfo.getChannelCallCfgList().isEmpty()) {
            rglog.error("<{}-{}>交易未配置交易通道服务调用配置信息！", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                item.getCallIndex().equals(ChannelBaseService.FIRST_CHANNEL_CALL_INDEX)).collect(Collectors.toList());
        ChannelCallCfg channelCallCfg = channelCallSceneDiscern(posScanQrCodePreAuthCancelRequest, channelCallCfgList);
        Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
        ChannelBaseService channelBaseService = (ChannelBaseService) channelClasz.newInstance();
        channelBaseService.callService(txnInfo, orderInfo, channelCallCfg.getBizScene(), request);

        /* 组装应答报文 */
        PosScanQrCodePreAuthCancelResponse posScanQrCodePreAuthCancelResponse = (PosScanQrCodePreAuthCancelResponse) GlobalTransUtil.getCacheValue(TransCacheConstant.BIZ_RESPONSE);
        posScanQrCodePreAuthCancelResponse = null == posScanQrCodePreAuthCancelResponse?new PosScanQrCodePreAuthCancelResponse():posScanQrCodePreAuthCancelResponse;
        posScanQrCodePreAuthCancelResponse.setHeader(posScanQrCodePreAuthCancelRequest.getHeader());
        posScanQrCodePreAuthCancelResponse.setAcqInstCode(mchntInfo.getSignInstId());
        posScanQrCodePreAuthCancelResponse.setPayId(userOrderInfo.getSysSeqNum());

        BizResponse bizResponse = new BizResponse();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setResult(posScanQrCodePreAuthCancelResponse);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        PosScanQrCodePreAuthCancelResponse posScanQrCodePreAuthCancelResponse = (PosScanQrCodePreAuthCancelResponse) bizResponse.getResult();
        ConvertUtil.convertInput(posScanQrCodePreAuthCancelResponse);
    }

    /**
     * 生成用户订单信息
     *
     * @param posScanQrCodePreAuthCancelRequest 请求信息
     * @return 用户订单信息
     * @throws Exception 异常
     */
    private UserOrderInfo generateUserOrderInfo(PosScanQrCodePreAuthCancelRequest posScanQrCodePreAuthCancelRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        String userId = xmlTreeUtil.getXmlTreeStringValue(McpsTreeNodeConstant.USER_ID);
        UserOrderInfo origUserOrderInfo = (UserOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_USER_ORDER_INFO);
        if (null == origUserOrderInfo){
            rglog.error("原用户订单不存在!");
            throw new BizException(RespCodeEnum.ORDER_NOEXIT.getRespCode(),RespCodeEnum.ORDER_NOEXIT.getRespDesc());
        }
        UserOrderInfo userOrderInfo = new UserOrderInfo();
        /*初始化用户订单信息*/
        userOrderInfo.setInstId(posScanQrCodePreAuthCancelRequest.getHeader().getInstId());
        userOrderInfo.setTxnNum(posScanQrCodePreAuthCancelRequest.getHeader().getTxnNum());
        userOrderInfo.setBizType(posScanQrCodePreAuthCancelRequest.getHeader().getBizType());
        userOrderInfo.setMsgSrcId(posScanQrCodePreAuthCancelRequest.getHeader().getSrcSysId());
        userOrderInfo.setTransChannelId(posScanQrCodePreAuthCancelRequest.getHeader().getChanlId());
        userOrderInfo.setMchntOrderId(sysSeqNum);
        userOrderInfo.setUserOrderId(sysSeqNum);
        userOrderInfo.setSysSeqNum(sysSeqNum);
        userOrderInfo.setOrderAmt(origUserOrderInfo.getOrderAmt());
        userOrderInfo.setOrderCcy(AppParamConstant.DEFAULT_ORDER_CCY);
        userOrderInfo.setTxnDate(DateUtil.getCurrentDate());
        userOrderInfo.setTxnTime(DateUtil.getCurrentTime());
        userOrderInfo.setOrderDesc(origUserOrderInfo.getOrderDesc());
        userOrderInfo.setNeedPayAmt(userOrderInfo.getOrderAmt());
        userOrderInfo.setRealPayAmt(userOrderInfo.getOrderAmt());
        userOrderInfo.setUserId(userId);
        userOrderInfo.setFrontSeqNum(posScanQrCodePreAuthCancelRequest.getHeader().getTraceNo());
        userOrderInfo.setOrigSysSeqNum(origUserOrderInfo.getSysSeqNum());
        userOrderInfo.setOrderCreateTime(DateUtil.getCurrentDateTime("yyyyMMddHHmmss"));
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(userOrderInfo.getInstId(), McpsParamConstant.NORMAL_TXNKEY_PREFIX, McpsParamConstant.ORDER_LIFE);
        String orderLife = null == sysParam ? "180" : sysParam.getParamValue().trim();
        userOrderInfo.setOrderExpiryTime(DateUtil.getDateByTimeStamp(System.currentTimeMillis() + Long.parseLong(orderLife) * 1000, "yyyyMMddHHmmss"));
        userOrderInfo.setOrderStatus(OrderStatusEnum.INIT.getStatus());
        userOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        userOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        userOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        return userOrderInfo;
    }

    /**
     * 生成商户订单信息
     *
     * @param posScanQrCodePreAuthCancelRequest 请求信息
     * @param userOrderInfo             用户订单信息
     * @return 商户户订单信息
     * @throws Exception 异常
     */
    private MchntOrderInfo generateMchntOrderInfo(PosScanQrCodePreAuthCancelRequest posScanQrCodePreAuthCancelRequest, UserOrderInfo userOrderInfo) throws Exception {
        MchntOrderInfo mchntOrderInfo = new MchntOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, mchntOrderInfo);
        /*设置商户订单中其他字段值,需要查询商户信息表，获取商户相关信息*/
        mchntOrderInfo.setMchntNo(posScanQrCodePreAuthCancelRequest.getMchntNo());
        /*若存在 设置连锁商户门店*/
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
        if (null != mchntInfo.getChainMchntNo()) {
            mchntOrderInfo.setChainMchntNo(mchntInfo.getChainMchntNo());
        }
        mchntOrderInfo.setRealSettleAmt(userOrderInfo.getOrderAmt());
        mchntOrderInfo.setMchntName(mchntInfo.getMchntName());
        mchntOrderInfo.setTermNo(posScanQrCodePreAuthCancelRequest.getTermNo());
        mchntOrderInfo.setMchntSettleAmt("0");
        mchntOrderInfo.setUserId(posScanQrCodePreAuthCancelRequest.getUserId());
        mchntOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        mchntOrderInfo.setIndustryType(mchntInfo.getIndustryType());
        /*收单机构号*/
        mchntOrderInfo.setAcqInstCode(mchntInfo.getSignInstId());
        /*业务产品代码*/
        mchntOrderInfo.setBizProdCode(this.txnInfo.getSrcTxnAuthCfg().getBizProdCode());
        mchntOrderInfo.setRealSettleFlag(AppParamConstant.NO);
        /*保存连锁商户于商户订单表,连锁门店并且非独立清算*/
        if ("11".equals(mchntInfo.getMchntType()) && "N".equals(mchntInfo.getIndependentDataFlag())) {
            mchntOrderInfo.setChainMchntNo(mchntInfo.getChainMchntNo());
        }
        return mchntOrderInfo;
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        PosScanQrCodePreAuthCancelRequest posScanQrCodePreAuthCancelRequest = (PosScanQrCodePreAuthCancelRequest) request;
        /* 业务细分：bizType：00-微信条码预授权撤销(暂不支持)，01-支付宝条码预授权撤销，02-银联二维码条码预授权撤销 */
        String bizType = posScanQrCodePreAuthCancelRequest.getHeader().getBizType();
        Optional<ChannelCallCfg> channelCallCfgOpt = channelCallCfgList.stream().filter(item ->
                item.getBizScene().equals(bizType)).findFirst();
        return channelCallCfgOpt.orElse(null);
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        if (TransStatusEnum.TRANS_SUCC.equals(transStatusEnum) && null != needUpdateOrderInfo && null != needUpdateOrderInfo.getUserOrderInfo()){
            /* 交易应答对象赋值 */
            PosScanQrCodePreAuthCancelResponse posScanQrCodePreAuthCancelResponse = (PosScanQrCodePreAuthCancelResponse) GlobalTransUtil.getCacheValue(TransCacheConstant.BIZ_RESPONSE);
            posScanQrCodePreAuthCancelResponse = null == posScanQrCodePreAuthCancelResponse?new PosScanQrCodePreAuthCancelResponse():posScanQrCodePreAuthCancelResponse;
            Optional<PayOrderInfo> payOrderInfoOpt = needUpdateOrderInfo.getPayOrderInfoList().stream().filter(item ->
                    item.getMsgDstId().equals(channelCallCfg.getCallChannelId()) && item.getDstCallIndex().equals(channelCallCfg.getCallIndex())).findFirst();
            if (payOrderInfoOpt.isPresent()) {
                OrderInfoBean orderInfo = new OrderInfoBean();
                BeanUtil.beanCopy(payOrderInfoOpt.get(), orderInfo);
                BeanUtil.nullValueCopy(payOrderInfoOpt.get(), orderInfo);
                posScanQrCodePreAuthCancelResponse.setOrderInfo(orderInfo);
            }
            GlobalTransUtil.setCacheValue(TransCacheConstant.BIZ_RESPONSE, posScanQrCodePreAuthCancelResponse);
            /* 更新原订单状态 */
            String transStatus = needUpdateOrderInfo.getUserOrderInfo().getTransStatus();
            String bizStatus = needUpdateOrderInfo.getUserOrderInfo().getBizStatus();
            if (TransStatusEnum.TRANS_SUCC.getStatus().equals(transStatus) && BizStatusEnum.FINISH.getStatus().equals(bizStatus)){
                UserOrderInfo origUserOrderInfo = (UserOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_USER_ORDER_INFO);
                MchntOrderInfo origMchntOrderInfo = (MchntOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_MCHNT_ORDER_INFO);
                PayOrderInfo origPayOrderInfo = (PayOrderInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.ORIG_PAY_ORDER_INFO);
                Objects.requireNonNull(origUserOrderInfo).setBizStatus(BizStatusEnum.CANCEL.getStatus());
                Objects.requireNonNull(origMchntOrderInfo).setBizStatus(BizStatusEnum.CANCEL.getStatus());
                Objects.requireNonNull(origPayOrderInfo).setBizStatus(BizStatusEnum.CANCEL.getStatus());
                OrderService orderService = new OrderServiceImpl();
                List<MchntOrderInfo> origMchntOrderInfoList = new ArrayList<>();
                origMchntOrderInfoList.add(origMchntOrderInfo);
                if (!orderService.updateOrderInfo(origUserOrderInfo,origMchntOrderInfoList,origPayOrderInfo)){
                    rglog.error("更新原订单失败!");
                    throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(),RespCodeEnum.UPDATE_ORDER_ERROR.getRespDesc());
                }
            }
        }
        return transStatusEnum;
    }
}
